﻿using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Collections;
using System.Collections.Generic;
using ServerServices;
using System.Configuration;
using CommonLib;

namespace PadiCalClient
{
    class PadiCalCliente : MarshalByRefObject, IClientPuppet
    {

        private string[] servers = { "central-1", "central-2", "central-3" };

        private String Username;
        private String _port;

        private TcpChannel tcp;

        private Boolean connected = false;

        IServerService serverOperations;

        private bool init = false;

        Agenda agenda;

        

        public PadiCalCliente(String user, String p)
        {

            Console.WriteLine("Client {0} initiated...", user);

            Username = user;

            _port = p;

            //tcp = new TcpChannel(Int32.Parse(_port));
            //ChannelServices.RegisterChannel(tcp, false);

            StartPuppetService();

            agenda = new Agenda(Username, tcp);

            connect(p);
            init = true;
        }

        public void connect(string port)
        {
            Console.WriteLine("connecting client on port:"+port);
            ChannelServices.UnregisterChannel(tcp);
            _port = port;
            tcp = new TcpChannel(Int32.Parse(port));
            ChannelServices.RegisterChannel(tcp, false);
            this.connected = true;
            ObjRef clientservice = RemotingServices.Marshal(agenda, "ClientService");
            Register();
            if (!connected)
            {
                if (init)
                {
                    ChannelServices.UnregisterChannel(tcp);
                }
                _port = port;
                tcp = new TcpChannel(Int32.Parse(port));
                ChannelServices.RegisterChannel(tcp, false);
                connected = true;
                clientservice = RemotingServices.Marshal(agenda, "ClientService");
                Register();
            }
        }

        private IServerService chooseServer()
        {
            //Random r = new Random();

            //int choosen = r.Next(servers.Length);

            //string serverAddress = ConfigurationSettings.AppSettings[servers[choosen]];
            string serverAddress = ConfigurationSettings.AppSettings["central-1"];

            return (IServerService)Activator.GetObject(typeof(IServerService),
            "tcp://" + serverAddress + "/ServerService");
        }


        private void Register()
        {

            serverOperations = chooseServer();

            agenda.user = serverOperations.peerRegister(Username, _port);

            Console.WriteLine("Address: " + agenda.user.getAddress());

        }

        private void StartPuppetService()
        {
            ObjRef clientpuppet = RemotingServices.Marshal(this, "ClientPuppet");
        }


        static void Main(string[] args)
        {

            PadiCalCliente a = new PadiCalCliente(args[0], args[1]);

            Console.ReadLine();
        }



        public string[] getCalendar()
        {
            return agenda.getCalendar();
        }

        public bool isConnected()
        {
            return this.connected;
        }


        public void disconnect()
        {
            Console.WriteLine("Disconnected...");
            this.connected = false;

            serverOperations = chooseServer();

            serverOperations.cancelRegister(Username);

            RemotingServices.Disconnect(agenda);


        }

        public void receivedInitReservation(InitReservation init)
        {
            agenda.receivedInitReservation(init);
        }

        /*public void beginReservation(string name, ArrayList users, ArrayList slots)
        {
            agenda.beginReservation(name, users, slots);
        }*/

        public ArrayList getSlotReservations(int index)
        {
            return agenda.getSlotReservations(index);
        }

    }
}
